﻿using System;
using System.Collections.Generic;
using Finance.Data;
using Finance.ViewModels;

namespace Finance.Controllers
{
	public interface IDocumentController : IDocumentBaseController
	{
		void GetProductsWithPrices(IList<ProductSearchResult> productsSearchResult, string value, int maxSearchResultCount, Guid guid, DateTime docDate);
	}

	internal class DocumentController : DocumentBaseController, IDocumentController
	{
		public DocumentController(FinanceDataBase dataBase) : base(dataBase)
		{
		}

		public void GetProductsWithPrices(
			IList<ProductSearchResult> targetList,
			string value,
			int maxSearchResultCount,
			Guid contractorId,
			DateTime docDate)
		{
			using (var reader = FinanceDataBase.Sql.ExecuteReader(
					"select name, productId from product where name like @p0", "%" + value + "%"))
			{
				int count = 0;
				while (count < maxSearchResultCount && reader.Read())
				{
					var productId = (Guid)reader["productid"];

					var productResult = new ProductSearchResult
					{
						ProductId = (Guid)reader["productid"],
						Name = (string)reader["name"],
						Price = contractorId.Equals(Guid.Empty) ? 0 :
							GetProductPrice(productId, contractorId, docDate)
					};

					targetList.Add(productResult);
					count++;
				}
			}
		}

		private const string FindLatestPriceBeforeQuery =
			"select documentproduct.price from documentproduct" +
			" inner join document on document.documentid = documentproduct.documentid" +
			" where document.DocDatetime <= @p0 and document.contractorid = @p1 and documentproduct.productid = @p2 " +
			"order by docdatetime desc";

		private const string FindEarlyPriceAfterQuery =
			"select documentproduct.price from documentproduct" +
			" inner join document on document.documentid = documentproduct.documentid" +
			" where document.DocDatetime >= @p0 and document.contractorid = @p1 and documentproduct.productid = @p2 " +
			"order by docdatetime";

		public decimal GetProductPrice(Guid productId, Guid contractorId, DateTime docDate)
		{
			//Try to find latest price before this document
			var result = FinanceDataBase.Sql.ExecuteScalar(FindLatestPriceBeforeQuery, docDate, contractorId, productId);
			if (result != null)
				return (decimal)result;

			//Try to find early price after this document
			result = FinanceDataBase.Sql.ExecuteScalar(FindEarlyPriceAfterQuery, docDate, contractorId, productId);
			if (result != null)
				return (decimal)result;

			return 0;
		}
	}
}
